/*
 *  constant_info.h
 *
 *  Copyright (C) 2011  Jason<linux8192@gmail.com>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef _CONSTANT_INFO_H_
#define _CONSTANT_INFO_H_

#include "type.h"

/*
 * Constant tag definations
 */
#define CONSTANT_UTF8				1
#define CONSTANT_INTEGER			3
#define CONSTANT_FLOAT				4
#define CONSTANT_LONG				5
#define CONSTANT_DOUBLE				6
#define CONSTANT_CLASS				7
#define CONSTANT_STRING				8
#define CONSTANT_FIELD_REF			9
#define CONSTANT_METHOD_REF			10
#define CONSTANT_INTERFACE_METHOD_REF		11
#define CONSTANT_NAME_AND_TYPE			12

#define SIZEOF_CONSTANT_UTF8			3
#define SIZEOF_CONSTANT_INTEGER			5
#define SIZEOF_CONSTANT_FLOAT			5
#define SIZEOF_CONSTANT_LONG			9
#define SIZEOF_CONSTANT_DOUBLE			9
#define SIZEOF_CONSTANT_CLASS			3
#define SIZEOF_CONSTANT_STRING			3
#define SIZEOF_CONSTANT_FIELD_REF		5
#define SIZEOF_CONSTANT_METHOD_REF		5
#define SIZEOF_CONSTANT_INTERFACE_METHOD_REF	5
#define SIZEOF_CONSTANT_NAME_AND_TYPE		5

#define __get_constant_info_length(c)		(SIZEOF_##c)

/*
 * Constant pool struct definitions
 */
typedef struct _constant_pool_info {
	u1	tag;
} cp_info_t;

typedef struct _constant_utf8_info {
	cp_info_t	base;
	u2		length;
	u1		bytes[1];
} cp_utf8_info_t;

typedef struct _constant_integer_info {
	cp_info_t	base;
	u4		bytes;
} cp_integer_info_t;

typedef struct _constant_float_info {
	cp_info_t	base;
	union {
		u4	bytes;
		float	float_value;
	};
} cp_float_info_t;

typedef struct _constant_long_info {
	cp_info_t	base;
	u8		bytes;
} cp_long_info_t;

typedef struct _constant_double_info {
	cp_info_t	base;
	union {
		u8	bytes;
		double	double_value;
	};
} cp_double_info_t;

typedef struct _constant_class_info {
	cp_info_t	base;
	u2		name_index;
} cp_class_info_t;

typedef struct _constant_string_info {
	cp_info_t	base;
	u2		string_index;
} cp_string_info_t;

typedef struct _constant_field_ref_info {
	cp_info_t	base;
	u2		class_index;
	u2		name_and_type_index;
} cp_field_ref_info_t;

typedef struct _constant_method_ref_info {
	cp_info_t	base;
	u2		class_index;
	u2		name_and_type_index;
} cp_method_ref_info_t;

typedef struct _constant_interface_method_ref_info {
	cp_info_t	base;
	u2		class_index;
	u2		name_and_type_index;
} cp_interface_method_ref_info_t;

typedef struct _constant_name_and_type_info {
	cp_info_t	base;
	u2		name_index;
	u2		descriptor_index;
} cp_name_and_type_info_t;


/*
 * Functions
 */

int parse_constant_pool(const char *cp_buff, cp_info_t **list, const int cp_count);
cp_info_t *get_constant_info_by_index(cp_info_t **cp_list, int index);

char *get_utf8_string_by_cp_index(cp_info_t **cp_list, int cp_index);
char *get_utf8_string_from_cp(const cp_utf8_info_t *cp_utf8);
void copy_utf8_string_from_cp(char **buf, const cp_utf8_info_t *cp_utf8);
void copy_class_name_from_cp(char **buf, const cp_info_t **cp_list, int class_const_index);

void dump_constant_pool(cp_info_t **cp_list, const int cp_count);


#endif /* _CONSTANT_INFO_H_ */
